home *** CD-ROM | disk | FTP | other *** search
/ Windows News 2005 February / WN_129_CD.iso / Windows / Extensions Firefox / FlashGot / flashgot-0.5.3.xpi / chrome / flashgot.jar / content / flashgot / FlashGot.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-11-14  |  18.4 KB  |  851 lines

  1. /***** BEGIN LICENSE BLOCK *****
  2.    - Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.    -
  4.    - The contents of this file are subject to the Mozilla Public License Version
  5.    - 1.1 (the "License"); you may not use this file except in compliance with
  6.    - the License. You may obtain a copy of the License at
  7.    - http://www.mozilla.org/MPL/
  8.    -
  9.    - Software distributed under the License is distributed on an "AS IS" basis,
  10.    - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.    - for the specific language governing rights and limitations under the
  12.    - License.
  13.    -
  14.    - The Original Code is "FlashGot".
  15.    -
  16.    - The Initial Developer of the Original Code is Giorgio Maone.
  17.    - Portions created by the Initial Developer are Copyright (C) 2004
  18.    - the Initial Developer. All Rights Reserved.
  19.    -
  20.    - Contributor(s): Giorgio Maone <g.maone @ informaction.com>
  21.    -
  22.    - Alternatively, the contents of this file may be used under the terms of
  23.    - either the GNU General Public License Version 2 or later (the "GPL"), or
  24.    - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  25.    - in which case the provisions of the GPL or the LGPL are applicable instead
  26.    - of those above. If you wish to allow use of your version of this file only
  27.    - under the terms of either the GPL or the LGPL, and not to allow others to
  28.    - use your version of this file under the terms of the MPL, indicate your
  29.    - decision by deleting the provisions above and replace them with the notice
  30.    - and other provisions required by the LGPL or the GPL. If you do not delete
  31.    - the provisions above, a recipient may use your version of this file under
  32.    - the terms of any one of the MPL, the GPL or the LGPL.
  33.    -
  34.    - ***** END LICENSE BLOCK *****/
  35.  
  36. #include "stdafx.h"
  37. #include <sys/stat.h>
  38. #include <comdef.h>
  39. #include <atlbase.h>
  40. #include <atlcom.h>
  41. #include <objbase.h>
  42.  
  43. #define BUF_SIZE 1024
  44.  
  45. char g_buf[BUF_SIZE];
  46. wchar_t g_wbuf[BUF_SIZE];
  47.  
  48.  
  49. // [START DOWNLOAD MANAGER SUPPORT CLASSES]
  50.  
  51. using namespace std;
  52. class DMSupport
  53. {
  54.  
  55. protected:
  56.     
  57.     static BOOL createProcess(char *commandLine, PROCESS_INFORMATION *pi) {
  58.         STARTUPINFO si;
  59.         ZeroMemory( &si, sizeof(si) );
  60.         si.cb = sizeof(si);
  61.         
  62.         PROCESS_INFORMATION *mypi=NULL;
  63.         if(!pi) {
  64.             pi=mypi=new PROCESS_INFORMATION;
  65.         }
  66.         ZeroMemory(pi, sizeof(pi) );
  67.  
  68.         
  69.         BOOL ret=CreateProcess( NULL, 
  70.                 commandLine, // Command line. 
  71.                 NULL,             // Process handle not inheritable. 
  72.                 NULL,             // Thread handle not inheritable. 
  73.                 FALSE,            // Set handle inheritance to FALSE. 
  74.                 0,                // No creation flags. 
  75.                 NULL,             // Use parent's environment block. 
  76.                 NULL,             // Use parent's starting directory. 
  77.                 &si,              // Pointer to STARTUPINFO structure.
  78.                 pi )             // Pointer to PROCESS_INFORMATION structure.
  79.             ;
  80.         
  81.         if(mypi) {
  82.             closeProcess(mypi);
  83.             delete mypi;
  84.         }
  85.         
  86.         return ret;
  87.     }
  88.  
  89.     static void closeProcess(PROCESS_INFORMATION *pi) {
  90.         CloseHandle( pi->hProcess );
  91.         CloseHandle( pi->hThread );
  92.     }
  93.  
  94.  
  95. public:
  96.     enum OpType { OP_ONE=0, OP_SEL=1, OP_ALL=2, OP_MIN=OP_ONE, OP_MAX=OP_ALL };
  97.     
  98.     virtual void check(void) = 0;
  99.     virtual void dispatch(const int linksCount, const int linesCount, const bstr_t* parm, const OpType opType ) = 0;
  100.     virtual const char *getName(void) = 0;
  101.     
  102.  
  103. };
  104.  
  105.  
  106.  
  107. class DMSupportCOM :
  108.     public DMSupport
  109. {
  110.  
  111. #define COMCALL(Call) if(hr=FAILED(Call)) throw _com_error(hr);
  112.  
  113. private:
  114.     HRESULT hr;
  115.     CComDispatchDriver  comObj;
  116.     CComPtr<IDispatch>  lpTDispatch;
  117.     
  118. protected:
  119.     
  120.  
  121.     void prepareCOMObj() {
  122.         if(!comObj) {
  123.             COMCALL(lpTDispatch.CoCreateInstance(_bstr_t(getProgId())));
  124.             comObj=lpTDispatch;
  125.         }
  126.     }
  127.  
  128.     static SAFEARRAY *createSafeArray(int elemCount) 
  129.     {
  130.         SAFEARRAYBOUND bounds [1]; 
  131.         bounds[0].cElements=elemCount;
  132.         bounds[0].lLbound=0;
  133.         return SafeArrayCreate(VT_VARIANT, 1, bounds);
  134.     }
  135.     
  136.     virtual const char * getProgId() = 0;
  137.     
  138.     void getMemberID(char *memberName, DISPID *dispid) {
  139.         USES_CONVERSION;
  140.         OLECHAR FAR* oleMember=A2OLE(memberName);
  141.         prepareCOMObj();
  142.         COMCALL(comObj->GetIDsOfNames(IID_NULL, &oleMember, 1, LOCALE_SYSTEM_DEFAULT, dispid));
  143.     }
  144.  
  145.     void invoke(DISPID *dispid, VARIANT *parms, const unsigned int parmsCount) {    
  146.         prepareCOMObj();
  147.         COMCALL(comObj.InvokeN(*dispid,parms,parmsCount,NULL));
  148.     }
  149.     
  150.     void invoke(char *memberName, VARIANT *parms, const unsigned int parmsCount) {
  151.         DISPID dispid;
  152.         getMemberID(memberName,&dispid);
  153.         invoke(&dispid,parms,parmsCount);
  154.     }
  155.  
  156.     void putProperty(char *propertyName, VARIANT val) {
  157.         USES_CONVERSION;
  158.         LPCOLESTR oleMember=A2COLE(propertyName);
  159.         prepareCOMObj();
  160.         COMCALL(comObj.PutPropertyByName(oleMember, &val));
  161.     }
  162.  
  163. public:
  164.     
  165.     void check() 
  166.     {
  167.         CLSID clsid;
  168.         COMCALL(CLSIDFromProgID(_bstr_t(getProgId()),&clsid));
  169.     }
  170.  
  171.     
  172. };
  173.  
  174.  
  175.  
  176.  
  177. class DMSFlashGet :
  178.     public DMSupportCOM
  179. {
  180.  
  181.  
  182. protected:
  183.     
  184.     const char * getProgId() { return "JetCar.Netscape"; }
  185.     
  186. public:
  187.     
  188.     const char * getName() { return "FlashGet"; }
  189.  
  190.     void dispatch(const int linksCount, const int linesCount, const bstr_t* parms, const OpType opType )
  191.     {
  192.         int elemCount=linksCount * 2 + 1; // linksCount * 2 (url,info)
  193.         SAFEARRAY *psa=createSafeArray(elemCount);
  194.         
  195.         VARIANT v;
  196.         v.vt = VT_BSTR;
  197.         long ix[]={0};
  198.         long j=0, fetchCount=3;
  199.         for (; ix[0] < elemCount ; ix[0]++) {
  200.             v.bstrVal=parms[j];
  201.             SafeArrayPutElement(psa, ix, &v);
  202.             // skip cookie and postData
  203.             if(--fetchCount) {
  204.                 ++j;
  205.             } else {
  206.                 j+=3;
  207.                 fetchCount=2;
  208.             }
  209.         }
  210.         
  211.         
  212.         v.vt = VT_ARRAY | VT_VARIANT | VT_BYREF; // VBScript Array
  213.         v.pparray=&psa;
  214.         
  215.         invoke("AddUrlList",&v,1);
  216.         SafeArrayDestroy(psa);
  217.     }
  218. };
  219.  
  220.  
  221. class DMSGetRight :
  222.     public DMSupport
  223. {
  224.  
  225. private:
  226.     static char *findGetRight(HKEY baseKey, char *leafPath) {
  227.         long res;
  228.         HKEY hk;
  229.         char *path=NULL;
  230.  
  231.         if( (res=RegOpenKeyEx(baseKey,leafPath,0,KEY_QUERY_VALUE,&hk))==ERROR_SUCCESS)
  232.         {
  233.         
  234.         
  235.             char *installKey="InstallDir";
  236.             long pathLen=0;    
  237.             if((res=RegQueryValueEx(hk,installKey,0,NULL,NULL,(LPDWORD)&pathLen))==ERROR_SUCCESS) 
  238.             {
  239.                 char *exeLeaf="\\getright.exe";
  240.                 path=new char[pathLen+strlen(exeLeaf)];
  241.                 BOOL fileExists=FALSE;
  242.                 if((res=RegQueryValueEx(hk,installKey,0,NULL,(LPBYTE)path,(LPDWORD)&pathLen))==ERROR_SUCCESS)
  243.                 {
  244.                     strcat(path,exeLeaf);
  245.                     struct stat statbuf;
  246.                     fileExists=!stat(path,&statbuf);  
  247.                 }
  248.                 if(!fileExists) {
  249.                     delete path;
  250.                     path=NULL;
  251.                 }
  252.             }
  253.             RegCloseKey(hk);    
  254.         }
  255.  
  256.         return path;
  257.         
  258.     }
  259.     
  260.     static char *findGetRight() 
  261.     {
  262.         char *path;
  263.         if(    ( path=findGetRight(HKEY_CURRENT_USER,"Software\\Headlight\\GetRight\\Config") )
  264.              || ( path=findGetRight(HKEY_LOCAL_MACHINE,"Software\\Headlight\\GetRight") ) )
  265.         {
  266.             return path;
  267.         }
  268.         throw "Can't find GetRight executable";
  269.     }
  270.  
  271.     static char *createCmdLine(char *path, char *arg) {
  272.         char *cmdLine=new char[strlen(path)+strlen(arg)+5];
  273.         sprintf(cmdLine,"\"%s\" %s",path,arg);
  274.         return cmdLine;
  275.     }
  276.  
  277. public:
  278.     
  279.     const char * getName() { return "GetRight"; }
  280.  
  281.     void check() 
  282.     {
  283.         delete findGetRight();
  284.     }
  285.     void dispatch(const int linksCount, const int linesCount, const bstr_t* parms, const OpType opType ) 
  286.     {
  287.         char *cmdLine=NULL;
  288.         char *path=NULL;
  289.         BOOL ret=createProcess(cmdLine=createCmdLine(path=findGetRight(),(char *)parms[linksCount?1:0]),NULL);
  290.         if(cmdLine) {
  291.             delete cmdLine;
  292.         }
  293.         if(path) delete path;
  294.         if(!ret) throw "Can't launch GetRight";
  295.     }
  296. };
  297.  
  298.  
  299. class DMSLeechGet :
  300.     public DMSupportCOM
  301. {
  302. protected:
  303.     void invoke(char *memberName,_bstr_t parm) {
  304.         VARIANT v;
  305.         v.vt=VT_BSTR;
  306.         v.bstrVal=parm;
  307.         DMSupportCOM::invoke(memberName,&v,1);
  308.     }
  309.  
  310. public:
  311.     
  312.     
  313.     void dispatch(const int linksCount, const int linesCount, const bstr_t* parms, const OpType opType ) 
  314.     {    
  315.         if(linksCount>0) 
  316.         {
  317.             this->invoke("Wizard",parms[1]);
  318.         } 
  319.         else 
  320.         {
  321.             this->invoke("Parse",parms[0]);
  322.         }
  323.     }
  324. };
  325.  
  326. class DMSLeechGet2002 :
  327.     public DMSLeechGet
  328. {
  329.     
  330. protected:
  331.     const char * getProgId() 
  332.     {
  333.         return "LeechGetIE.AddURL";
  334.     }
  335. public:
  336.     const char * getName() { return "LeechGet 2002"; }
  337. };
  338.  
  339. class DMSLeechGet2004 :
  340.     public DMSLeechGet
  341. {
  342. protected:
  343.     const char * getProgId() 
  344.     {
  345.         return "LeechGetIE.LeechIE";
  346.     }
  347. public:
  348.     const char * getName() { return "LeechGet 2004"; }
  349. };
  350.  
  351. class DMSNet_Transport :
  352.     public DMSupportCOM
  353. {
  354.  
  355. protected:
  356.     
  357.     const char * getProgId() { return "NTIEHelper.NTIEAddUrl"; }
  358.  
  359. public:
  360.     const char * getName() { return "Net Transport"; }
  361.  
  362.     void dispatch(const int linksCount, const int linesCount, const bstr_t* parms, const OpType opType )
  363.     {
  364.         SAFEARRAY *psaa[2]=
  365.         {
  366.             createSafeArray(linksCount),
  367.             createSafeArray(linksCount)
  368.         };
  369.         
  370.         
  371.         VARIANT vstr;
  372.         vstr.vt = VT_BSTR;
  373.         long ix[]={0};
  374.         for(int j=1; ix[0]<linksCount; ix[0]++) 
  375.         {
  376.             for(int a=0; a<2; a++) 
  377.             {
  378.                 vstr.bstrVal=parms[j++];
  379.                 SafeArrayPutElement(psaa[a], ix, &vstr);
  380.             }
  381.             j+=2; // skipping cookie & postData;
  382.         }
  383.  
  384.         //AddList(referrer,urls, remarks);
  385.         VARIANT v[3];
  386.         v[2].vt=VT_BSTR;
  387.         v[2].bstrVal=parms[0];
  388.         v[1].vt=v[0].vt=VT_VARIANT | VT_BYREF ;
  389.         SafeArrayAccessData(psaa[0], (void **)&(v[1].pvarVal));
  390.         SafeArrayAccessData(psaa[1], (void **)&(v[0].pparray));
  391.         invoke("AddList",v,3);
  392.  
  393.         SafeArrayUnlock(psaa[1]);
  394.         SafeArrayUnlock(psaa[0]);
  395.         SafeArrayDestroy(psaa[0]);
  396.         SafeArrayDestroy(psaa[1]);
  397.     }
  398. };
  399.  
  400. class DMSWestByte :
  401.     public DMSupportCOM
  402. {
  403.  
  404. public:
  405.  
  406.  
  407.     void dispatch(const int linksCount, const int linesCount, const bstr_t* parms, const OpType opType )
  408.     {
  409.         if(linksCount>0)
  410.         {
  411.             
  412.             VARIANT v[2];
  413.             v[0].vt = VT_BSTR ;
  414.             v[0].bstrVal=parms[0]; // referer
  415.             
  416.             if(linksCount==1) 
  417.             {
  418.                 v[1].vt = VT_BSTR; // VBScript Array
  419.                 v[1].bstrVal=parms[1];
  420.                 invoke("AddURL",v,2);
  421.             } 
  422.             else 
  423.             { 
  424.  
  425.                 int elemCount=linksCount * 2;
  426.                 
  427.         
  428.                 SAFEARRAY *psa=createSafeArray(elemCount);
  429.                 
  430.                 VARIANT vstr;
  431.                 vstr.vt = VT_BSTR;
  432.                 long ix[]={0};
  433.                 long j=1,fetchCount=2;
  434.  
  435.                 for (; ix[0] < elemCount; ix[0]++) {
  436.                     vstr.bstrVal=parms[j];
  437.                     SafeArrayPutElement(psa, ix, &vstr);
  438.                     // skip cookie and postData
  439.                     if(--fetchCount) {
  440.                         ++j;
  441.                     } else {
  442.                         j+=3;
  443.                         fetchCount=2;
  444.                     }
  445.                 }
  446.                 
  447.                 
  448.                 v[1].vt = VT_ARRAY | VT_VARIANT | VT_BYREF; // VBScript Array
  449.                 v[1].pparray=&psa;
  450.                 
  451.                 
  452.  
  453.                 invoke("AddURLs",v,2);
  454.  
  455.                 SafeArrayDestroy(psa);
  456.             }
  457.         }
  458.     }
  459.     
  460. };
  461.  
  462. class DMSDownloadMaster :
  463.     public DMSWestByte
  464. {
  465. protected:
  466.     const char * getProgId() { return "DMIE.MoveURL"; }
  467. public:
  468.     const char * getName() { return "Download Master"; }
  469. };
  470.  
  471. class DMSInternetDownloadAccelerator :
  472.     public DMSWestByte
  473. {
  474. protected:
  475.     const char * getProgId() { return "IDAIE.MoveURLIDA"; }
  476. public:
  477.     const char * getName() { return "Internet Download Accelerator"; }
  478. };
  479.  
  480.  
  481.  
  482. #import "progid:WG.WGUrlListReceiver.1"
  483. using namespace DataStretcherLib;
  484. class DMSFreeDownloadManager :
  485.     public DMSupportCOM
  486. {
  487.  
  488. protected:
  489.     
  490.     const char * getProgId() { return "WG.WGUrlListReceiver"; }
  491.  
  492. public:
  493.     
  494.     const char * getName() { return "Free Download Manager"; }
  495.  
  496.     void dispatch(const int linksCount, const int linesCount, const bstr_t* parms, const OpType opType )
  497.     {
  498.         if(linksCount>0)
  499.         {
  500.             if(linksCount<2)
  501.             {
  502.                 IWGUrlReceiverPtr fdm(__uuidof(WGUrlReceiver));
  503.                 fdm->PutReferer(parms[0]);
  504.                 fdm->PutUrl(parms[1]);
  505.                 fdm->PutComment(parms[2]);
  506.                 fdm->AddDownload();
  507.             }
  508.             else
  509.             {
  510.                 IWGUrlListReceiverPtr fdm(__uuidof(WGUrlListReceiver));
  511.                 fdm->PutReferer(parms[0]);
  512.                 int elemCount=linksCount*4;
  513.                 for(int j=1; j<=elemCount; j+=3) { // why j+=3? because we're skipping cookie & postData
  514.                     fdm->PutUrl(parms[j++]);
  515.                     fdm->PutComment(parms[j]);
  516.                     fdm->AddUrlToList();
  517.                 }
  518.                 fdm->ShowAddUrlListDialog();
  519.             }
  520.         }
  521.     }
  522.     
  523. };
  524.  
  525. class DMSReGet :
  526.     public DMSupportCOM
  527. {
  528.  
  529.  
  530. public:
  531.     
  532.     
  533.     void dispatch(const int linksCount, const int linesCount, const bstr_t* parms, const OpType opType ) 
  534.     {    
  535.         BOOL multiple=linksCount>1;
  536.         DISPID di_AddDownload;
  537.         DMSupportCOM::getMemberID(multiple?"AddDownloadToList":"AddDownload",&di_AddDownload);
  538.         int elemCount=linksCount*4;
  539.         VARIANT v[5];
  540.         v[0].vt=v[1].vt=v[2].vt=v[3].vt=v[4].vt=VT_BSTR;
  541.         
  542.         v[3].bstrVal=parms[0]; // referer
  543.         for(int j=1; j<=elemCount;) 
  544.         {
  545.             v[4].bstrVal=parms[j++]; // URL
  546.             v[1].bstrVal=parms[j++]; // info
  547.             v[2].bstrVal=parms[j++]; // cookie
  548.             v[0].bstrVal=parms[j++]; // postData
  549.             if(!SysStringLen(v[0].bstrVal)) v[0].bstrVal=NULL;
  550.             for(int attempts=120; attempts-->0;) 
  551.             { // we give ReGet 2min to wake up
  552.                 try 
  553.                 {
  554.                     if(!multiple) {
  555.                         putProperty("Url",v[4]);
  556.                         putProperty("Referer",v[3]);
  557.                         putProperty("Cookie",v[2]);
  558.                         putProperty("Info",v[1]);
  559.                         putProperty("PostData",v[0]);
  560.                         DMSupportCOM::invoke(&di_AddDownload,NULL,0);
  561.                     } else {
  562.                         DMSupportCOM::invoke(&di_AddDownload,v,5);
  563.                     }
  564.                     break;
  565.                 } 
  566.                 catch(_com_error ce)
  567.                 {
  568.                     Sleep(1000);
  569.                 }
  570.             }
  571.         }
  572.  
  573.         if(multiple) try 
  574.         { 
  575.             DMSupportCOM::invoke("FlushDownloadList",v,0);
  576.         } catch(...) {}
  577.     }
  578. };
  579.  
  580. class DMSReGetJr :
  581.     public DMSReGet
  582. {
  583.     
  584. protected:
  585.     const char * getProgId() 
  586.     {
  587.         return "ReGetJr.RegetDownloadApi";
  588.     }
  589. public:
  590.     const char * getName() { return "ReGet Junior"; }
  591. };
  592.  
  593. class DMSReGetDx :
  594.     public DMSReGet
  595. {
  596.     
  597. protected:
  598.     const char * getProgId() 
  599.     {
  600.         return "ReGetDx.RegetDownloadApi";
  601.     }
  602. public:
  603.     const char * getName() { return "ReGet Deluxe"; }
  604. };
  605.  
  606. class DMSReGetPro :
  607.     public DMSReGet
  608. {
  609.     
  610. protected:
  611.     const char * getProgId() 
  612.     {
  613.         return "ReGetPro.RegetDownloadApi";
  614.     }
  615. public:
  616.     const char * getName() { return "ReGet Pro"; }
  617. };
  618.  
  619.  
  620. // [END DOWNLOAD MANAGER SUPPORT CLASSES]
  621.  
  622.  
  623. typedef struct _DMSNode {
  624.     unsigned int id;
  625.     DMSupport *dms;
  626.     _DMSNode *prev;
  627. } DMSNode;
  628.  
  629.  
  630.  
  631. class DMSFactory 
  632. {
  633. private:
  634.     static DMSFactory *instance;
  635.     DMSNode *last;
  636.     DMSupport *add(DMSupport *dms) {
  637.         if(!last) {
  638.             (last=new DMSNode())->prev=NULL;
  639.             last->id=1;
  640.         } else {
  641.             DMSNode *newNode=new DMSNode();
  642.             newNode->prev=last;
  643.             newNode->id=last->id << 1;
  644.             last=newNode;
  645.         }
  646.         return last->dms=dms;
  647.     }
  648.  
  649.     DMSFactory() : last(NULL) {
  650.         add(new DMSDownloadMaster());
  651.         add(new DMSFlashGet());
  652.         add(new DMSFreeDownloadManager());
  653.         add(new DMSGetRight());
  654.         add(new DMSInternetDownloadAccelerator());
  655.         add(new DMSLeechGet2002());
  656.         add(new DMSLeechGet2004());
  657.         add(new DMSNet_Transport());
  658.         add(new DMSReGetDx());
  659.         add(new DMSReGetJr());
  660.         add(new DMSReGetPro());
  661.     }
  662.  
  663. public:
  664.     
  665.     static DMSFactory *getInstance() {
  666.         return instance?instance:instance=new DMSFactory();        
  667.     }
  668.     
  669.     
  670.     DMSupport *getDMS(char *name) {
  671.         DMSNode *cursor=last;
  672.         for(; cursor && strcmp(cursor->dms->getName(),name); cursor=cursor->prev);
  673.         return cursor 
  674.             ?cursor->dms
  675.             :NULL;    
  676.     }
  677.     
  678.     unsigned int checkAll() {
  679.         unsigned int retVal=0;
  680.         CoInitialize(NULL);
  681.         for(DMSNode *cursor=last; cursor; cursor=cursor->prev) {
  682.             try {
  683.                 fprintf(stdout,"%s|",cursor->dms->getName());
  684.                 cursor->dms->check();
  685.                 fprintf(stdout,"OK\n");
  686.                 continue;
  687.             } catch(_com_error ce) {
  688.                 fprintf(stdout,"BAD\nCOM error: %s\n", ce.ErrorMessage());
  689.             } catch(...) {
  690.                 fprintf(stdout,"BAD\nunexpected unknown error!\n");
  691.             }
  692.             retVal |= cursor->id;
  693.         }
  694.         CoUninitialize();
  695.         return retVal;
  696.     }
  697.  
  698.  
  699.  
  700.     ~DMSFactory() {
  701.         DMSNode *cursor=last;
  702.         while( cursor ) {
  703.             delete cursor->dms;
  704.             last=cursor;
  705.             cursor=last->prev;
  706.             delete last;
  707.         }
  708.     }
  709. };
  710. DMSFactory * DMSFactory::instance=NULL;
  711.  
  712.  
  713.  
  714.  
  715. char* readLine(FILE *stream, char *buf) 
  716. {
  717.     
  718.     char *res=fgets(buf,BUF_SIZE,stream);
  719.     if(res) 
  720.     {
  721.         size_t lastPos=strlen(res)-1;
  722.         while(lastPos>=0 && 
  723.             (res[lastPos]==0x0a || res[lastPos]==0x0d)
  724.             ) res[lastPos--]='\0';
  725.     }
  726.     return res;
  727. }
  728.  
  729.  
  730. void fail(char *msg, int code) 
  731. {
  732.     MessageBox(NULL, msg,
  733.                       "FlashGot error",
  734.                       MB_OK | MB_ICONERROR);
  735.     exit(code);
  736. }
  737.  
  738.  
  739. DMSupport* createDMS(char *name) {
  740.     DMSupport *res=DMSFactory::getInstance()->getDMS(name);
  741.     if(res) return res;
  742.     sprintf(g_buf,"Unsupported Download Manager %s", name);
  743.     fail(g_buf,-8000);
  744.     return NULL;
  745. }
  746.  
  747. wchar_t *UTF8toUnicode(char *buf) {
  748.     return buf && (
  749.         MultiByteToWideChar(CP_UTF8,0,buf,-1,g_wbuf,BUF_SIZE) 
  750.         || MultiByteToWideChar(CP_ACP,0,buf,-1,g_wbuf,BUF_SIZE))
  751.         ? g_wbuf : L""
  752.         ;
  753. }
  754.  
  755. int main(int argc, char* argv[])
  756. {
  757.     char *fname;
  758.     FILE *f;
  759.     
  760.     
  761.     if(argc<2 || strcmp(argv[1],"-o") == 0 )
  762.     {
  763.         if(argc>=2) 
  764.         {
  765.             freopen(argv[2],"w", stdout);
  766.             freopen(argv[2],"a", stderr);
  767.         }
  768.         exit(DMSFactory::getInstance()->checkAll());
  769.         
  770.     } 
  771.     else if(!(f=fopen(fname=argv[1],"rb")))  
  772.     {
  773.         sprintf(g_buf,"Can't open file %s",fname);
  774.         fail(g_buf,0x01000);
  775.     }
  776.     else
  777.     {    
  778.         if(!feof(f))    
  779.         {
  780.         
  781.             CoInitialize(NULL);
  782.             DMSupport *dms = NULL;
  783.             const char *errMsg="Download manager not properly installed.\n%s";
  784.             BOOL done=FALSE;
  785.             try 
  786.             {
  787.                 int linksCount=atoi(readLine(f,g_buf));
  788.                 int linesCount=linksCount*4+1; // referer + (url + info  + cookie + postdata) * 4 
  789.  
  790.  
  791.                 char *header[3];
  792.                 char header_buf[BUF_SIZE];
  793.                 strcpy(header_buf,g_buf);
  794.                 char *cur=header_buf;
  795.                 for(int j=0; j<3 ; j++ ) {
  796.                     if(cur && (cur=strchr(cur,';')) ) {
  797.                         cur[0]='\0';
  798.                         header[j]=++cur;
  799.                     } else {
  800.                         header[j]=NULL;
  801.                     }
  802.                 }
  803.                 
  804.                 char *dmName=header[0]?header[0]:"FlashGet";
  805.                 int typeId=header[1]?atoi(header[1]) : DMSupport::OP_ALL;
  806.                 
  807.                 if(typeId<DMSupport::OP_MIN||typeId>DMSupport::OP_MAX) {
  808.                     typeId=DMSupport::OP_ALL;    
  809.                 }
  810.                 
  811.                 bstr_t *parms =new bstr_t[linesCount];
  812.                 
  813.                 for(int j=0; j<linesCount; j++) {
  814.                     parms[j]=bstr_t(UTF8toUnicode(readLine(f,g_buf)));
  815.                 }
  816.                 
  817.                 (dms=createDMS(dmName))->dispatch(linksCount,linesCount,parms,(DMSupport::OpType)typeId);
  818.                 done=TRUE;
  819.             } 
  820.             catch(_com_error ce)
  821.             {
  822.                 sprintf(g_buf,errMsg,ce.ErrorMessage());
  823.             }
  824.             catch(char *ex) {
  825.                 sprintf(g_buf,errMsg,ex);
  826.             }
  827.             catch(...) {
  828.                 sprintf(g_buf,errMsg,"");
  829.             }
  830.             if(dms) delete dms;
  831.             CoUninitialize();
  832.             if(!done) fail(g_buf,0x02000);
  833.         }
  834.         
  835.         else 
  836.         {
  837.             sprintf(g_buf,"Temporary file %s is empty",fname);
  838.             fail(g_buf,0x03000);
  839.         }
  840.         fclose(f);
  841.         //remove(fname);
  842.     }
  843.     return 0;
  844. }
  845.  
  846. int WINAPI
  847. WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
  848. {
  849.     return main(__argc, __argv); 
  850. }
  851.